package com.ai.module.order.service.impl;

import com.ai.module.chat.common.constant.RedisKeyStringConstant;
import com.ai.module.order.domain.entity.UserOrderEntity;
import com.ai.module.order.domain.entity.WXOrderVo;
import com.ai.module.order.domain.entity.WxOrderEntity;
import com.ai.module.order.domain.vo.WeChatPayStatus;
import com.ai.module.order.en.UserServiceType;
import com.ai.module.order.mapper.UserOrderMapper;
import com.ai.module.order.service.UserOrderService;
import com.ai.module.order.service.WxOrderService;
import com.ai.module.user.domain.entity.UserConfigEntity;
import com.ai.module.user.domain.entity.UserPointsRecordEntity;
import com.ai.module.user.domain.vo.UserLoginInfo;
import com.ai.module.user.enu.PointSource;
import com.ai.module.user.service.UserConfigService;
import com.ai.module.user.service.UserPointsService;
import com.ai.module.chat.util.DateUtils;
import com.ai.module.chat.util.RedisTemplateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;


import static com.ai.module.mj.constant.enums.TaskAction.USER_PAY;

/**
 * @author: heJinQin
 * @create: 2024-04-06 12:37
 * @description:
 **/
@Service
public class UserOrderServiceImpl extends ServiceImpl<UserOrderMapper, UserOrderEntity> implements UserOrderService {

    @Autowired
    private UserPointsService userPointsService;

    @Autowired
    @Lazy
    private WxOrderService wxOrderService;

    @Autowired
    private UserConfigService userConfig;


    @Override
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void saveUserOrder( WeChatPayStatus weChatPayStatus) {
        // 支付成功的 页面
        String orderId = weChatPayStatus.getOrderId();
        Double amount = weChatPayStatus.getAmount();
        UserOrderEntity userOrder = new UserOrderEntity();
        userOrder.setOrderId(orderId);
        userOrder.setAmount(amount.intValue());
        userOrder.setSuccessTime(weChatPayStatus.getSuccessTime());
        userOrder.setTradeType(weChatPayStatus.getTradeType());
        userOrder.setTransactionId(weChatPayStatus.getTransactionId());

        // 根据 订单 ID查询 订单Info
        //   1, 生成积分记录 2, 新增用户积分 3, 进行vip逻辑 4,刷新用户数据
        String serviceTypeKey = String.format(
                RedisKeyStringConstant.WE_CHAT_payServiceType, orderId);
        WXOrderVo wxOrderVo = RedisTemplateUtils.get(serviceTypeKey);

        if (wxOrderVo == null) {
//             查询数据
            WxOrderEntity  wxOrder = wxOrderService.getOne(
                    new LambdaQueryWrapper<WxOrderEntity>()
                            .eq(WxOrderEntity::getOrderId, orderId)
            );
            wxOrderVo = new WXOrderVo();
            BeanUtils.copyProperties(wxOrder,wxOrderVo);
        }
        UserServiceType useServiceType = wxOrderVo.getServiceType();
        String userId = wxOrderVo.getUserId();

        UserConfigEntity userConfigE = userConfig.getOne(
                new LambdaQueryWrapper<UserConfigEntity>()
                        .eq(UserConfigEntity::getUserId, userId)
        );
        UserPointsRecordEntity pointsRecord = new UserPointsRecordEntity();
        LocalDateTime vipExpire = userConfigE.getVipExpire();
        if (vipExpire.isBefore(LocalDateTime.now())) {
            vipExpire=LocalDateTime.now();
        }
        int vipPoint = 0;
        PointSource pointSource= PointSource.pointPay;
        switch (useServiceType) {
            case POINTS:
                dealUserPoint(orderId,
                        userConfigE,
                        pointSource,
                        amount.intValue(),
                        pointsRecord);
                break;
            case YEAR_VIP:
                vipExpire=  vipExpire.plusYears(1);
                pointSource=PointSource.yearVip;
                break;
            case MONTH_VIP:
                vipExpire= vipExpire.plusMonths(1);
                pointSource=PointSource.monthVip;
                break;
            case ONE_DAY_VIP:
                vipExpire= vipExpire.plusDays(1);
                pointSource=PointSource.dayVip;
            break;
            case SEVEN_DAY_VIP:
                vipExpire=  vipExpire.plusDays(7);
                pointSource=PointSource.sevenVip;

        }
        userConfigE.setVipExpire(vipExpire);
        userConfigE.setVip(1);
        int points = useServiceType.getPoints();
        dealUserPoint(userId,
                userConfigE,
                pointSource,
                points,
                pointsRecord);
        userOrder.setUserId(userId);
        userOrder.setTradeType(userId);
        this.saveOrUpdate(userOrder);
    }

    private void dealUserPoint(
                               String orderId,
                               UserConfigEntity userConfigE,
                               PointSource pointSource,
                               int amount,
                               UserPointsRecordEntity pointsRecord) {

        Integer points = userConfigE.getPoints();
        String userId = userConfigE.getUserId();
        if (amount <= 0) {
            return;
        }
        Integer realPoint = points + amount;
        userConfigE.setPoints(realPoint);
        String userTokenKey = String.format(RedisKeyStringConstant.USER_ID_TOKEN, userId);
        String userToken = RedisTemplateUtils.get(userTokenKey);
        String userInfoKey = String.format(RedisKeyStringConstant.USER_INFO, userToken);
        UserLoginInfo userLoginInfo = RedisTemplateUtils.get(userInfoKey);
        Integer infoPoint = userLoginInfo.getPoints();
        LocalDateTime vipExpire = userConfigE.getVipExpire();
        userLoginInfo.setVipExpire(DateUtils.format(vipExpire));
        userLoginInfo.setVip(userConfigE.getVip());
        //  if (infoPoint <= ) 说明是正在 绘画, 这里的积分 比真实的少
        pointsRecord.setBeforePoints(infoPoint);
        pointsRecord.setUserId(userId);
        pointsRecord.setAfterPoints(infoPoint + amount);
        pointsRecord.setBusinessId(orderId);
        pointsRecord.setPointType(USER_PAY);
        pointsRecord.setSource(pointSource);
        pointsRecord.setSourceId(orderId);
        userPointsService.save(pointsRecord);
        userLoginInfo.setPoints(infoPoint + amount);
        Integer realPoints = userLoginInfo.getRealPoints();
        if (realPoints== null){
            realPoints = infoPoint;
        }
        userLoginInfo.setRealPoints(realPoints + amount);
        RedisTemplateUtils.set(userInfoKey, userLoginInfo, DateUtils.TIME_DAY * 7);
        userConfig.updateById(userConfigE);
    }
}
